#ifndef STATIC_HPP
#define STATIC_HPP

// SFML
#include <SFML/Audio.hpp>
#include <SFML/Graphics.hpp>
#include <SFML/Network.hpp>
#include <SFML/System.hpp>
#include <SFML/Window.hpp>

// System
namespace sf
{
	template <typename S>
	S Random(sf::Randomizer& random, S begin, S end)
	{
		return random.Random(begin, end);
	}

	template <unsigned int U, typename In>
	In UtfDecode(Utf<U>& utf, In begin, In end, Uint32& output, Uint32 replacement = 0)
	{
		return utf.Decode(begin, end, output, replacement);
	}

	template <unsigned int U, typename Out>
	Out UtfEncode(Utf<U>& utf, Uint32 input, Out output, Uint8 replacement = 0)
	{
		return utf.Encode(input, output, replacement);
	}

	template <unsigned int U, typename In>
	In UtfNext(Utf<U>& utf, In begin, In end)
	{
		return utf.Next(begin, end);
	}

	template <unsigned int U, typename In>
	std::size_t UtfCount(Utf<U>& utf, In begin, In end)
	{
		return utf.Count(begin, end);
	}

	template <unsigned int U, typename In, typename Out>
	Out UtfFromAnsi(Utf<U>& utf, In begin, In end, Out output, const std::locale& locale = GetDefaultLocale())
	{
		return utf.FromAnsi(begin, end, output, locale);
	}

	template <unsigned int U, typename In, typename Out>
	Out UtfFromWide(Utf<U>& utf, In begin, In end, Out output)
	{
		return utf.FromWide(begin, end, output);
	}

	template <unsigned int U, typename In, typename Out>
	Out UtfToAnsi(Utf<U>& utf, In begin, In end, Out output, char replacement = 0, const std::locale& locale = GetDefaultLocale())
	{
		return utf.ToAnsi(begin, end, output, replacement, locale);
	}

	template <unsigned int U, typename In, typename Out>
	Out UtfToWide(Utf<U>& utf, In begin, In end, Out output, wchar_t replacement = 0)
	{
		return utf.ToWide(begin, end, output, replacement);
	}

	template <unsigned int U, typename In, typename Out>
	Out UtfToUtf8(Utf<U>& utf, In begin, In end, Out output)
	{
		return utf.ToUtf8(begin, end, output);
	}

	template <unsigned int U, typename In, typename Out>
	Out UtfToUtf16(Utf<U>& utf, In begin, In end, Out output)
	{
		return utf.ToUtf16(begin, end, output);
	}

	template <unsigned int U, typename In, typename Out>
	Out UtfToUtf32(Utf<U>& utf, In begin, In end, Out output)
	{
		return utf.ToUtf32(begin, end, output);
	}

// Audio
#ifdef AUDIOPACKAGE
	void ListenerSetGlobalVolume(sf::Listener& listener, float volume);
	float ListenerGetGlobalVolume(sf::Listener& listener);
	void ListenerSetPosition(sf::Listener& listener, float x, float y, float z);
	void ListenerSetPosition(sf::Listener& listener, const sf::Vector3f& position);
	sf::Vector3f ListenerGetPosition(sf::Listener& listener);
	void ListenerSetDirection(sf::Listener& listener, float x, float y, float z);
	void ListenerSetDirection(sf::Listener& listener, const sf::Vector3f& direction);
	sf::Vector3f ListenerGetDirection(sf::Listener& listener);
#endif //AUDIOPACKAGE

// Graphics
	sf::Shape LineShape(sf::Shape& shape, float p1x, float p1y, float p2x, float p2y, float thickness, const sf::Color& color, float outline = 0.f, const sf::Color& outlineColor = sf::Color(0, 0, 0));
	sf::Shape LineShape(sf::Shape& shape, const sf::Vector2f& start, const sf::Vector2f& end, float thickness, const sf::Color& color, float outline = 0.f, const sf::Color& outlineColor = Color(0, 0, 0));
	sf::Shape RectangleShape(sf::Shape& shape, float left, float top, float width, float height, const sf::Color& color, float outline = 0.f, const sf::Color& outlineColor = sf::Color(0, 0, 0));
	sf::Shape RectangleShape(sf::Shape& shape, const sf::FloatRect& rectangle, const sf::Color& color, float outline = 0.f, const sf::Color& outlineColor = sf::Color(0, 0, 0));
	sf::Shape CircleShape(sf::Shape& shape, float x, float y, float radius, const sf::Color& color, float outline = 0.f, const sf::Color& outlineColor = sf::Color(0, 0, 0));
	sf::Shape CircleShape(sf::Shape& shape, const sf::Vector2f& center, float radius, const sf::Color& color, float outline = 0.f, const sf::Color& outlineColor = sf::Color(0, 0, 0));
	sf::Matrix3 Transformation(sf::Matrix3& matrix, const sf::Vector2f& origin, const sf::Vector2f& translation, float rotation, const sf::Vector2f& scale);
	sf::Matrix3 Projection(sf::Matrix3& matrix, const sf::Vector2f& center, const sf::Vector2f& size, float rotation);

// Window
	sf::VideoMode VideoModeGetDesktopMode(sf::VideoMode& videomode);
	const std::vector<sf::VideoMode> VideoModeGetFullscreenModes(sf::VideoMode& videomode);
}

#endif //STATIC_HPP